package com.project.modules.quartz;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.project.common.service.RedisService;
import com.project.modules.redEnvelope.model.TblRecord;
import com.project.modules.redEnvelope.model.TblRedEnvelope;
import com.project.modules.redEnvelope.model.TblSign;
import com.project.modules.redEnvelope.service.TblRecordService;
import com.project.modules.redEnvelope.service.TblRedEnvelopeService;
import com.project.modules.redEnvelope.service.TblSignService;
import com.project.modules.redEnvelope.utils.RedEnvelopeUtil;
import com.project.modules.ums.service.UmsUserService;
import com.project.security.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static com.project.modules.redEnvelope.constant.Constant.*;

@Slf4j
public class EndJob implements Job {

    //    @Autowired
    private final RedisService redisService = SpringUtil.getBean(RedisService.class);

    //    @Autowired
    private final TblRecordService recordService = SpringUtil.getBean(TblRecordService.class);

    //    @Autowired
    private final UmsUserService userService = SpringUtil.getBean(UmsUserService.class);
    //    @Autowired
    private final TblRedEnvelopeService redEnvelopeService = SpringUtil.getBean(TblRedEnvelopeService.class);
    private final TblSignService signService = SpringUtil.getBean(TblSignService.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        Long redId = context.getJobDetail().getJobDataMap().getLong("redId");
        settleRedEnvelope(redId);
        // 释放锁资源
        redisService.releaseLock(RED_ENVELOPE_LOCK + redId);
    }

    private void settleRedEnvelope(Long redId) {
        log.info("开始结算" + redId);
        // 机器人抢红包
        addRobRobots(redId);
        // 用户 -> 得分
        Map<Long, Integer> map = RedEnvelopeUtil.transferUserScore(redisService.hGetAll(RED_ENVELOPE_SCORE + redId));
        // 结算红包雨，放入Redis中
        map = MapUtil.sortByValue(map, true);
        map.entrySet().forEach(longIntegerEntry -> {
            log.info(longIntegerEntry.getKey() + "->" + longIntegerEntry.getValue());
        });
        List<TblRecord> recordList = new ArrayList<>();
        Iterator<Map.Entry<Long, Integer>> iterator = map.entrySet().iterator();
        // 所有分配掉的红包
        BigDecimal sum = BigDecimal.ZERO;
        while (iterator.hasNext()) {
            Map.Entry<Long, Integer> userScoreEntry = iterator.next();
            final Long userId = userScoreEntry.getKey();
            final Integer score = userScoreEntry.getValue();
            BigDecimal earnedMoney = (BigDecimal) redisService.lPop(RED_ENVELOPE_CREATE_KEY + redId);
            if (earnedMoney == null) {
                log.info("分配完毕" + redId);
                break;
            }

            // 把红包分发给用户
            redEnvelopeService.income(userId, earnedMoney);
//            redEnvelopeService.incomeAndNotice(redId,userId, earnedMoney, "恭喜您抢到大红包啦");
            redisService.hSet(RED_ENVELOPE_CONSUME_KEY + redId, userId + "", earnedMoney, SECONDS_OF_DAY);
            log.info("用户 {} 抢到了 {} 元红包", userId, earnedMoney);
            sum = sum.add(earnedMoney);
            TblRecord record = new TblRecord();
            record.setReceiveAmount(earnedMoney);
            record.setReceviceUserId(userId);
            record.setScore(score);
            record.setReceiveAmount(earnedMoney);
            record.setRedId(redId);
            recordList.add(record);
        }
        log.info("持久化。。。");
        recordService.saveBatch(recordList);
        // 把红包分发给企业，并发送通知
        final TblRedEnvelope envelope = redEnvelopeService.getById(redId);
        final String username = envelope.getCreateBy();
        BigDecimal totalAmount = envelope.getTotalAmount();
        BigDecimal restAmount = totalAmount.subtract(sum).setScale(2, RoundingMode.HALF_UP);
        redEnvelopeService.incomeAndNotice(redId, userService.getByUsername(username).getId(),
                restAmount, "您的红包退回了部分", DateUtil.date());
    }

    private void addRobRobots(Long redId) {
        // 张佳敏
        addRobRobot(redId, 1387808782426112L);
        // 马宁
        addRobRobot(redId, 1387808573980672L);
        // 丁元
        addRobRobot(redId, 1387839975849984L);
        // 张无忌
        addRobRobot(redId, 1388152956411904L);
        // 郑艺权
        addRobRobot(redId, 1388189044703232L);
    }

    private void addRobRobot(Long redId, Long userId) {
        // 防止测试人员登录机器人账号抢红包
        if (signService.count(new LambdaQueryWrapper<TblSign>()
                .eq(TblSign::getRedId, redId).eq(TblSign::getUserId, userId)) > 0) {
            return;
        }
        int randomScore = RandomUtil.randomInt(-20, 30);
        signService.save(new TblSign(redId, userId));
        redisService.incr(RED_ENVELOPE_CREATE_COUNT + redId, 1L);
        // 报名人数放缓存
        redisService.hSet(RED_ENVELOPE_SCORE + redId, userId + "", randomScore, RED_ENVELOPE_DURING_SECONDS);
    }


}
